<template>
  <NForm
    ref="formRef"
    :show-label="formOption.showLabel"
    :label-width="formOption.labelWidth"
    :label-align="formOption.labelAlign"
    :label-placement="formOption.labelPlacement"
    :size="formOption.size"
    :show-require-mark="formOption.showRequireMark"
    :require-mark-placement="formOption.requireMarkPlacement"
    :show-feedback="formOption.showFeedback"
    :validate-messages="formOption.validateMessages"
    :disabled="loading"
    :model="formData"
    :rules="formRules"
    :class="`nv-form nv-form__mode-${props.mode}`"
  >
    <template v-if="formOption.group">
      <NvSteps
        v-if="formOption.group.type === 'steps'"
        v-model:form="formData"
        v-model:current="current"
        v-model:status="stepStatus"
        :option="formOption"
        :mode="props.mode"
      >
        <template v-for="(_, name) in slots" #[name]="slotData">
          <slot :name v-bind="slotData || {}" />
        </template>
      </NvSteps>
      <NvCollapse
        v-else
        v-model:form="formData"
        :option="formOption"
        :mode="props.mode"
      >
        <template v-for="(_, name) in slots" #[name]="slotData">
          <slot :name v-bind="slotData || {}" />
        </template>
      </NvCollapse>
    </template>
    <NvFormFields
      v-else
      v-model:form="formData"
      :fields="formOption.fields"
      :option="formOption"
      :mode="props.mode"
    >
      <template v-for="(_, name) in slots" #[name]="slotData">
        <slot :name v-bind="slotData || {}" />
      </template>
    </NvFormFields>

    <!-- 用于触发form的submit事件，原submit按钮可能被传到form外部，导致回车触发不了submit事件 -->
    <button
      v-show="false"
      :type="formOption.submitOnEnter === false ? 'button' : 'submit'"
      @click="submit"
    />

    <Teleport
      v-if="formOption.formActions !== false"
      defer
      :disabled="!formActions?.teleportTo"
      :to="formActions?.teleportTo"
    >
      <NvFormActions
        :actions="formActions"
        :size="formOption.size"
        :mode="props.mode"
        :group="props.option.group"
        :current
        :submit-loading="loading"
        @submit="submit"
        @clear="clear"
        @prev-step="prevStep"
        @next-step="nextStep"
      >
        <template v-for="name in ['form_actions', 'form_actions_pre']" #[name]="slotData">
          <slot :name v-bind="slotData || {}" />
        </template>
      </NvFormActions>
    </Teleport>
  </NForm>
</template>

<script setup lang="ts">
import type { FormInst, StepsProps } from 'naive-ui'
import type { NvFormProps } from './types'
import type { RowData } from '@/types'
import { NForm } from 'naive-ui'
import { computed, ref } from 'vue'
import NvFormActions from './FormActions.vue'
import NvFormFields from './FormFields.vue'
import NvCollapse from './group/Collapse.vue'
import NvSteps from './group/Steps.vue'
import { useActions } from './use-actions'
import { useInit } from './use-init'
import { useOption } from './use-option'

const props = withDefaults(defineProps<NvFormProps>(), { current: 1, mode: 'add' })
const slots = defineSlots()

const formData = defineModel<RowData>('form', { required: true })
const loading = defineModel<boolean>('loading', { default: false })
const current = defineModel<number>('current', { default: 1 })

const { formRules } = useInit(props, formData)

const formRef = ref<FormInst>()
const stepStatus = ref<StepsProps['status']>('process')
const formOption = useOption(props)

const formActions = computed(() => {
  const { formActions } = formOption.value
  return typeof formActions === 'object' ? formActions : undefined
})

const actions = useActions(props, formRef, formData, loading, current, stepStatus)
const { clear, submit, prevStep, nextStep } = actions

defineExpose({ ...actions })
</script>
